package com.tobeface.sns.interfaces.admin;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.kissme.core.web.Webs;
import com.tobeface.sns.application.RegisterService;
import com.tobeface.sns.domain.User;
import com.tobeface.sns.domain.UserExistsException;
import com.tobeface.sns.domain.security.Member;
import com.tobeface.sns.interfaces.constants.SubjectAttrConstants;
import com.tobeface.sns.interfaces.exception.InvalidCaptchaException;
import com.tobeface.sns.interfaces.support.SubjectAwareController;
import com.tobeface.sns.interfaces.util.HttpCaptchaHelper;
import com.tobeface.sns.interfaces.util.JsonMessage;

/**
 * 
 * @author loudyn
 * 
 */
@Controller
public class RegisterController extends SubjectAwareController {

	private static final int REGISTER_USER_EXIST_EXCEPTION_CODE = 1;
	private static final int REGISTER_INVALID_CAPTCHA_EXCEPTION_CODE = 4;
	private static final int REGISTER_UNKNOWN_EXCEPTION_CODE = 8;

	private RegisterService registerService;

	@Autowired
	public RegisterController(RegisterService registerService) {
		this.registerService = registerService;
	}

	/**
	 * 
	 * @return
	 */
	@RequestMapping(value = { "/reg", "/register" }, method = RequestMethod.GET)
	public String register() {
		return "admin/register";
	}

	/**
	 * 
	 * @return
	 */
	@RequestMapping(value = "/register/ok", method = RequestMethod.GET)
	public String registerOk() {
		return "admin/register-ok";
	}

	/**
	 * 
	 * @param request
	 * @return
	 */
	@RequestMapping(value = { "/reg", "/register" }, method = RequestMethod.POST)
	public String register(HttpServletRequest request, HttpSession session) {

		try {

			checkCaptcha(request, session);
			User user = buildUser(request);

			registerService.mustNotRegister(user);

			encodePassword(user);
			// if user both not exist,keep go on
			registerService.register(user);

			login(user.getMember());
			applyToSubject(user);
			return "redirect:/register/ok";
			
		} catch (Exception e) {
			int code = translateRegisterExceptionCode(e);
			return "redirect:/register?code=" + code;
		}

	}

	private void encodePassword(User user) {
		Member member = user.getMember();
		member.encodePassword();
		user.setMember(member);
	}

	/**
	 * 
	 * @param username
	 * @return
	 */
	@RequestMapping(value = "/user/exists", method = RequestMethod.POST)
	@ResponseBody
	public JsonMessage isUserExists(@RequestHeader(value = "X-Requested-With", required = false) String requestedWith, @RequestParam("username") String username) {

		if (!Webs.isAjax(requestedWith)) {
			return JsonMessage.one().notOk();
		}

		return registerService.isUserExistsByUsername(username) ? JsonMessage.one().ok() : JsonMessage.one().notOk();
	}

	@RequestMapping(value = "/username/exists", method = RequestMethod.GET)
	@ResponseBody
	public boolean validateUsername(HttpServletRequest request, @RequestParam("username") String username) {
		return registerService.isUserExistsByUsername(username);

	}

	@RequestMapping(value = "/phone/exists", method = RequestMethod.GET)
	@ResponseBody
	public boolean validatePhone(HttpServletRequest request, @RequestParam("phone") String phone) {
		return registerService.isContactExistsByPhone(phone);
	}

	@RequestMapping(value = "/email/exists", method = RequestMethod.GET)
	@ResponseBody
	public boolean validateeEmail(HttpServletRequest request, @RequestParam("email") String email) {
		return registerService.isUserExistsByEmail(email);

	}

	private void checkCaptcha(HttpServletRequest request, HttpSession session) {
		String captcha = WebUtils.getCleanParam(request, "captcha");
		HttpCaptchaHelper.mustValidate(session);
		HttpCaptchaHelper.checkCaptcha(captcha, session);
	}

	private User buildUser(HttpServletRequest request) throws Exception {
		User entity = new User();
		bind(request, entity);
		return entity;
	}

	private void applyToSubject(User user) {
		getSubject().getSession().setAttribute(SubjectAttrConstants.USER_AWARE_CONSTANT, user);
	}

	private int translateRegisterExceptionCode(Exception e) {

		if (e instanceof InvalidCaptchaException) {
			return REGISTER_INVALID_CAPTCHA_EXCEPTION_CODE;
		}

		if (e instanceof UserExistsException) {
			return REGISTER_USER_EXIST_EXCEPTION_CODE;
		}

		return REGISTER_UNKNOWN_EXCEPTION_CODE;
	}

	private void login(Member member) {
		getSubject().login(new UsernamePasswordToken(member.getUsername(), member.getPassword()));
	}

}
